package com.aaron.messenger.data;

import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.aaron.messenger.MessengerApplication;
import com.aaron.messenger.R;
import com.aaron.messenger.ui.ChatActivity;
import com.aaron.messenger.ui.MainActivity;
import com.aaron.messenger.util.Utils;

import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.MulticastLock;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.widget.RemoteViews;

public class DataManager extends Service {
	private static final String TAG = "Datamanager";
	private static final int sNotifyId = 1;
	
	public class LocalBinder extends Binder {
		public DataManager getDataManager() {
            return DataManager.this;
        }
    }
	private boolean mServiceRunning = false;
	private MessageDispatcher mH;
	private MessengerDatabase mDB;
	private ChatManager mChatManager;
	private UserManager mUserManager;
	private FileTransferManager mFileTransferManager;
	private HandlerThread mThread;
	private MulticastLock mLock;
	private Handler mCallBackHandler;
	private NotificationManager mNM;
	private int mNotificationId = 0;
	private MessengerApplication mApplication;
	
	private final LocalBinder mBinder = new LocalBinder();
	
	public void onCreate() {
		super.onCreate();
		setup();
		setUsForeground();
	}
	
	private void setUsForeground() {
		Notification no = new Notification();
		
		Intent intent = new Intent();
		intent.setClass(this, MainActivity.class);
		PendingIntent pending = PendingIntent.getActivity(this, 0, intent, 0);
		
		no.contentIntent = pending;
		no.icon = R.drawable.app_icon;
		no.contentView = new RemoteViews(getPackageName(), R.layout.notify_layout);
		
		startForeground(sNotifyId, no);
	}
	
	private void setup() {
		WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
		mLock = wifi.createMulticastLock("hi");
		mLock.acquire();
		
		mNM = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		mApplication = (MessengerApplication) getApplication();
		
		Utils.getLocalIp(this);
	}
	
	@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}
	
	public void setCallBackHandler(Handler handler) {
		mCallBackHandler = handler;
	}
	
	public void login() {
		try {
			mUserManager.login();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalStateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public boolean isLogin() {
		return mUserManager.isLogin();
	}
	
	public void refresh() {
		mUserManager.clearUsers();
		login();
	}
	
	public void logout() {
		try {
			mUserManager.quit();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalStateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public int getChatSessionNumber() {
		return mChatManager.getChatSessions().size();
	}
	
	public ChatSession getChatSession(int index) {
		return mChatManager.getChatSessions().get(index);
	}
	
	public void closeChatSession(String target) {
		mChatManager.removeSession(target);
	}
	
	public ChatMessage getChatMessage(String target, int index) {
		return mChatManager.getSession(target).chatcache.get(index);
	}
	
	public int getChatContentNumber(String target) {
		ChatSession session = mChatManager.getSession(target);
		if(session != null) {
			return session.chatcache.size();
		} else {
			return 0;
		}
	}
	
	public void chat(ArrayList<String> info, byte metadata, String target) {
		ArrayList<Object> list = new ArrayList<Object>();
		list.add(info);
		list.add(metadata);
		list.add(target);
		Message msg = mH.obtainMessage(MessageDispatcher.MSG_SEND_DATA, list);
		msg.sendToTarget();
	}
	
	public ArrayList<User> getAllUsers() {
		return mUserManager.getUsers();
	}
	
	@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
		startService();
        return START_STICKY;
    }
	
	private void startService() {
		if(!mServiceRunning) {
			mThread = new HandlerThread("DataManagerThread");
			mThread.start();
			mH = new MessageDispatcher(mThread.getLooper());
	        mUserManager = UserManager.getInstance(this, mH);
			mChatManager = ChatManager.getInstance(mH);
			mFileTransferManager = FileTransferManager.getInstance();
			mDB = MessengerDatabase.getDB(this);
			mServiceRunning = true;
		}
	}
	
	public void onDestroy() {
		super.onDestroy();
		Message msg = mH.obtainMessage(MessageDispatcher.MSG_QUIT);
		msg.sendToTarget();
		mThread = null;
		mH = null;
		mLock.release();
		mLock = null;
		mServiceRunning = false;
	}
	
	public static final String USER_LOGIN = "com.aaron.messager.user_login";
	public static final String USER_QUIT = "com.aaron.messager.user_quit";
	public static final String USER_FEEDBACK = "com.aaron.messager.user_feedback";
	public static final String USER_STATECHANGED = "com.aaron.messager.user_state_changed";
	
	public static String getMessageString(int msgid) {
		switch(msgid) {
		case MessageDispatcher.MSG_USER_LOGIN:
			return USER_LOGIN;
		case MessageDispatcher.MSG_USER_QUIT:
			return USER_QUIT;
		case MessageDispatcher.MSG_USER_FEEDBACK:
			return USER_FEEDBACK;
		case MessageDispatcher.MSG_USER_STATE_CHANGED:
			return USER_STATECHANGED;
		default:
			return "";
		}
	}
	
	
	public class MessageDispatcher extends Handler {
		/**exit thread*/
		private static final int MSG_QUIT = 0;
		/**UserState MSG**/
		public static final int MSG_USER_LOGIN = 0x1;
		public static final int MSG_USER_QUIT = 0x2;
		public static final int MSG_USER_FEEDBACK = 0x3;
		public static final int MSG_USER_STATE_CHANGED = 0x4;
		
		/**Chat MSG*/
		public static final int MSG_SEND_DATA = 0x11;
		public static final int MSG_RECEIVE_DATA = 0x12;
		
		/**Update DB*/
		public static final int MSG_INSERT_FILETRANSFER_HISTROY = 0x21;
		public static final int MSG_INSERT_CHAT_HISTROY = 0x22;
		public static final int MSG_DELETE_FILETRANSFER_HISTROY = 0x23;
		public static final int MSG_DELETE_CHAT_HISTROY = 0x24;
		public static final int MSG_DELETE_ALL_CHAT_HISTROY = 0x25;
		public static final int MSG_QUERY_FILETRANSFER_HISTROY = 0x26;
		public static final int MSG_QUERY_CHAT_HISTROY = 0x27;
		
		public MessageDispatcher(Looper looper) {
			super(looper);
		}
		
		public void handleMessage(Message msg) {
			
			switch(msg.what) {
			case MSG_QUIT:
				getLooper().quit();
				mChatManager.exit();
				mChatManager = null;
				
				mUserManager.exit();
				mUserManager = null;
				
				mFileTransferManager.exit();
				mFileTransferManager = null;
				
				mDB.closeDB();
				mDB = null;
				break;
			case MSG_USER_LOGIN:
				if(mCallBackHandler != null) {
					User user = (User) msg.obj;
					Message message = mCallBackHandler.obtainMessage(MSG_USER_LOGIN, user);
					message.sendToTarget();
				}
				break;
			case MSG_USER_QUIT:
				if(mCallBackHandler != null) {
					User user = (User) msg.obj;
					Message message = mCallBackHandler.obtainMessage(MSG_USER_QUIT, user);
					message.sendToTarget();
				}
				break;
			case MSG_USER_FEEDBACK:
				if(mCallBackHandler != null) {
					Message message = mCallBackHandler.obtainMessage(MSG_USER_FEEDBACK);
					message.sendToTarget();
				}
				break;
			case MSG_USER_STATE_CHANGED:
				if(mCallBackHandler != null) {
					User user = (User) msg.obj;
					Message message = mCallBackHandler.obtainMessage(MSG_USER_STATE_CHANGED, user);
					message.sendToTarget();
				}
				break;
			case MSG_SEND_DATA:
				ArrayList<Object> list = (ArrayList<Object>) msg.obj;
				try {
					mChatManager.chat((ArrayList<String>)list.get(0), (Byte)list.get(1), (String)list.get(2));
				} catch (IllegalArgumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalStateException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				break;
			case MSG_RECEIVE_DATA:
				ChatMessage chatmsg = (ChatMessage) msg.obj;
				String activity = mApplication.getCurrentActivity();
				if(activity == null) {
					String text = chatmsg.getSource()+" say:"+chatmsg.getData().get(0);
					Notification notify = new Notification(android.R.id.icon, text, System.currentTimeMillis());
					Intent intent = new Intent();
					intent.setClass(DataManager.this,  ChatActivity.class);
					intent.putExtra("peer", chatmsg.src);
					intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
					PendingIntent pending = PendingIntent.getActivity(DataManager.this, 0, intent, 0);
					notify.setLatestEventInfo(DataManager.this, "New Message!", text, pending);
					mNM.notify(mNotificationId++, notify);
				} else {
					if(mCallBackHandler != null) {
						Message message = mCallBackHandler.obtainMessage(MSG_RECEIVE_DATA, msg.obj);
						message.sendToTarget();
					}
				}
				break;
			case MSG_DELETE_ALL_CHAT_HISTROY:
				mDB.cleanAllChatHistroy();
				break;
			case MSG_DELETE_CHAT_HISTROY:
				mDB.cleanChatHistroy((String) msg.obj);
				break;
			case MSG_DELETE_FILETRANSFER_HISTROY:
				mDB.cleanFileTransferHistroy();
				break;
			case MSG_INSERT_CHAT_HISTROY:
				break;
			case MSG_INSERT_FILETRANSFER_HISTROY:
				break;
			case MSG_QUERY_CHAT_HISTROY:
				break;
			case MSG_QUERY_FILETRANSFER_HISTROY:
				break;
			}
		}
		
	
	}
}
